import * as THREE from '../../build/three.module.js';
import Stats from '../../jsm/libs/stats.module.js';
import { GUI } from '../../jsm/libs/dat.gui.module.js';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050505);

const camera = new THREE.PerspectiveCamera(65, innerWidth / innerHeight, 1, 10);
camera.position.z = 2;

const vector = new THREE.Vector4(),
      instances = 5000, // 实例数量
      positions = [],
      offsets = [],
      colors = [],
      orientationsStart = [], // 开始方向
      orientationsEnd = []; // 结束方向

positions.push( 0.025, - 0.025, 0 );
positions.push( - 0.025, 0.025, 0 );
positions.push( 0, 0, 0.025 ); // 其他实例通过 offset 区分开位置

// attribute 设置
for ( var i = 0; i < instances; i ++ ) {


  offsets.push( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 );


  colors.push( Math.random(), Math.random(), Math.random(), Math.random() );


  vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
  vector.normalize();

  orientationsStart.push( vector.x, vector.y, vector.z, vector.w );


  vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
  vector.normalize();

  orientationsEnd.push( vector.x, vector.y, vector.z, vector.w );

}

var gmt = new THREE.InstancedBufferGeometry();
gmt.maxInstancedCount = instances;

gmt.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
gmt.setAttribute( 'offset', new THREE.InstancedBufferAttribute( new Float32Array( offsets ), 3 ) );
gmt.setAttribute( 'color', new THREE.InstancedBufferAttribute( new Float32Array( colors ), 4 ) );
gmt.setAttribute( 'orientationStart', new THREE.InstancedBufferAttribute( new Float32Array( orientationsStart ), 4 ) );
gmt.setAttribute( 'orientationEnd', new THREE.InstancedBufferAttribute( new Float32Array( orientationsEnd ), 4 ) );

var mtl = new THREE.RawShaderMaterial( {

  uniforms: {
    "time": { value: 1.0 },
    "sineTime": { value: 1.0 }
  },
  vertexShader: document.getElementById( 'vertexShader' ).textContent,
  fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
  side: THREE.DoubleSide,
  transparent: true

} );

const mesh = new THREE.Mesh(gmt, mtl);
scene.add(mesh);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

const stats = new Stats();

const gui = new GUI();
gui.add(gmt, 'maxInstancedCount', 0, instances);

const render = () => {
  const time = performance.now();

  mesh.rotation.y = time * .0005;
  mesh.material.uniforms['time'].value = time * .005;
  mesh.material.uniforms['sineTime'].value = Math.sin(mesh.material.uniforms['time'].value * .05);

  renderer.render(scene, camera);
}

const animate = () => {
  requestAnimationFrame(animate);

  stats.update();
  render();
}
animate();

const handleWindowResize = () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);
}
window.addEventListener('resize', handleWindowResize, false);